#include <iostream>
#include "../../Encriptacion/Kasiski.h"

#include <../lib/igloo/igloo.h>
using namespace igloo;
Context(testKasiski)
{

	Kasiski* ataque;
	string pathDelArchivoAAtacar;
	string pathDelArchivoDiccionario;
	fstream archivoARomper;
	fstream archivoDiccionario;

	void SetUp() {
		pathDelArchivoAAtacar = "archivoEncriptadoKasiski.txt";
		pathDelArchivoDiccionario = "diccionarioKasiski.txt";
		archivoARomper.open(pathDelArchivoAAtacar.c_str(), ios::in);
		archivoDiccionario.open(pathDelArchivoDiccionario.c_str(), ios::in);
		ataque = new Kasiski(pathDelArchivoAAtacar, pathDelArchivoDiccionario);
	}

	void TearDown() {
		delete ataque;
	}

	Spec(tomarPalabrasDelDiccinarioTest) {

		ocurrencia palabra;
		string lista = "lista";
		for (unsigned int i = 0; i < lista.length(); i++) {
			palabra .descripcion.push_back(lista.at(i));
		}

		vector<ocurrencia> palabras = ataque->getPalabrasDelDiccionario();

		Assert::That(palabras.at(0).descripcion.size(), Is().EqualTo(palabra .descripcion.size()));
		for (unsigned int i = 0; i < lista.length(); i++) {
			Assert::That(palabras.at(0).descripcion.at(i), Is().EqualTo(palabra .descripcion.at(i)));
		}
	}

	Spec(tomarPalabraDelDiccinarioPorLongitudTest) {

		char c;
		int cant = 0;
		vector<char> palabraABuscar;
		while (archivoARomper.get(c) && cant < 5) {
			palabraABuscar.push_back(c);
			cant++;
		}

		vector<ocurrencia> palabraResultado = ataque->busquedaPalabraEnDiccionarioPorLongitud(palabraABuscar);
		string palabraDelDiccionarioResultadoEsperadoUno = "votos";
		string palabraDelDiccionarioResultadoEsperadoDos = "lista";

		Assert::That(palabraResultado.at(1).descripcion.size(), Is().EqualTo(palabraABuscar.size()));
		for (unsigned int i = 0; i < palabraResultado.at(1).descripcion.size(); i++) {
			Assert::That(palabraResultado.at(1).descripcion.at(i), Is().EqualTo(palabraDelDiccionarioResultadoEsperadoUno.at(i)));
		}
		for (unsigned int i = 0; i < palabraResultado.at(0).descripcion.size(); i++) {
			Assert::That(palabraResultado.at(0).descripcion.at(i), Is().EqualTo(palabraDelDiccionarioResultadoEsperadoDos.at(i)));
		}
	}

	Spec(descifrarClaveTest) {

		char c;
		int cant = 0;
		vector<char> palabraCriptograma;
		while (archivoARomper.get(c) && cant < 5) {
			palabraCriptograma.push_back(c);
			cant++;
		}

		string palabraDelDiccionario = "lista";
		vector<ocurrencia> palabrasDiccionarios;
		ocurrencia palabra;
		for (unsigned int i = 0; i < palabraDelDiccionario.length(); i++) {
			palabra.descripcion.push_back(palabraDelDiccionario.at(i));
		}
		palabrasDiccionarios.push_back(palabra);

		vector<ocurrencia> clave = ataque->descifrarClave(palabrasDiccionarios, palabraCriptograma);

		string claveResultadoEsperado = "nacho";
		char* claveResultadoEsperadoChar = new char[5];
		for (unsigned int i = 0; i < 5; i++) {
			claveResultadoEsperadoChar[i] = claveResultadoEsperado.at(i);
		}

		Assert::That(clave.at(0).descripcion.size(), Is().EqualTo(claveResultadoEsperado.length()));
		for (unsigned int i = 0; i < 5; i++) {
			Assert::That(clave.at(0).descripcion.at(i), Is().EqualTo(claveResultadoEsperado.at(i)));
		}
	}

	Spec(ataqueTest) {

		vector<ocurrencia> clave = ataque->ataqueKasiski();

		string claveResultadoEsperado = "nacho";
		char* claveResultadoEsperadoChar = new char[5];
		for (unsigned int i = 0; i < 5; i++) {
			claveResultadoEsperadoChar[i] = claveResultadoEsperado.at(i);
		}

		Assert::That(clave.at(0).descripcion.size(), Is().EqualTo(claveResultadoEsperado.length()));
		for (unsigned int i = 0; i < 5; i++) {
			Assert::That(clave.at(0).descripcion.at(i), Is().EqualTo(claveResultadoEsperado.at(i)));
		}
	}
};
